package com.mby.controller;

import com.alibaba.fastjson.JSON;
import com.mby.entity.Debug;
import com.mby.entity.Error;
import com.mby.entity.User;
import com.mby.utils.HttpUtil;
import com.mby.utils.MbyException;
import com.mby.utils.MongoTools;
import com.mby.utils.WebConstant;
import io.rong.RongCloud;
import io.rong.models.Result;
import io.rong.models.response.TokenResult;
import io.rong.models.user.UserModel;
import jxl.write.Label;
import jxl.write.WritableSheet;
import jxl.write.WriteException;
import jxl.write.biff.RowsExceededException;
import net.sf.json.JSONObject;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by noah on 2018/4/15.
 */
public class BaseController {

    @Autowired
    //当前请求的request
    public HttpServletRequest request;

    //当前请求的response
    public HttpServletResponse response;

    //当前用户信息
    public String login_as = "";
    public boolean login_as_switch = true;

    public Map<String,Object> resultMap = new HashMap();

    //登录结果码
    private String resultCode;

    //token值
    public String token = null;
    public boolean isMoblie;
    public String cookie_name = null;

    //当前用户信息
    public User currentUser = new User();

    //参数JSONObject
    public JSONObject params = new JSONObject();

    public static RongCloud rongCloud;
    static {
        System.out.print("初始化融云引擎..."+WebConstant.APP_KEY+"..."+WebConstant.APP_SECRET);
        rongCloud = RongCloud.getInstance(WebConstant.APP_KEY, WebConstant.APP_SECRET);
        System.out.println("成功");
    }

    @Resource
    public MongoTools mongoTool;

    @ModelAttribute
    public void init() throws Exception {
        request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        response = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getResponse();
        getTokenFromCookie();
        String url = request.getRequestURI();
        if(!"/live/qiniu/token".equals(url) && url.indexOf("/init") == -1 && url.indexOf("/rabbit") == -1 && !"/live/rabbit/est15".equals(url) && !"/live/quality_check_time".equals(url) && !"/live/est_handover_time".equals(url) && !"/live/sessions".equals(url) && !"/live/users/sync".equals(url) && !"/live/groups".equals(url) && !"/live/groups/health_card_msg".equals(url) && !"/live/groups/mechanics".equals(url) && !"/live/service_status".equals(url) && !"/live/groups/members".equals(url) && !"/live/customers/last_sa".equals(url) && !"/live/groups/status".equals(url)){
            initUser();
        }
    }

    public User currentUser(){
        Subject subject = SecurityUtils.getSubject();
        return (User) subject.getSession().getAttribute("currentUser");
    }

    public void initUser() throws Exception {
        Subject subject = SecurityUtils.getSubject();
        subject.getSession().setAttribute("isMoblie",isMoblie);
        subject.getSession().setAttribute("mongoTool",mongoTool);
        if(login_as != null && login_as != "" && login_as_switch){
            UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("login_as",login_as);
            subject.login(usernamePasswordToken);
            subject = SecurityUtils.getSubject();
            currentUser = (User) subject.getSession().getAttribute("currentUser");
            resultCode = (String) subject.getSession().getAttribute("code");
            if (resultCode != "0" && !"0".equals(resultCode)) {
                respErr(resultCode);
            }
        }else{
            if (token == null) {
                respErr("Login Required");
            } else {
                UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(token, token);
                subject.login(usernamePasswordToken);
                currentUser = (User) subject.getSession().getAttribute("currentUser");
                resultCode = (String) subject.getSession().getAttribute("code");
                if (resultCode != "0" && !"0".equals(resultCode)) {
                    respErr(resultCode);
                }
            }
        }
    }

    //统一的返回错误信息方法，只有code和msg
    public void respErr(String errCode){
        String msg;
        Error error = initError(errCode);
        throw new MbyException(error);
    }

    //统一的返回数据方法
    public void respData(Object obj){
        postData(obj,null,null);
    }

    //统一的返回数据方法,带token
    public void respDataWithToken(Object obj,String token){
        postData(obj,token,null);
    }

    //发送数据
    public void postData(Object obj,String token,Integer seconds){
        Map<String,Object> responseMap = new HashMap<>();
        HttpServletResponse response = setHeader(seconds);
        if(token != null){
            Cookie cookie = new Cookie(cookie_name,token);
            cookie.setMaxAge(8*60*60);
            response.addCookie(cookie);
        }else if("#".equals(token)){
            Cookie cookie = new Cookie(cookie_name,null);
            response.addCookie(cookie);
        }
        responseMap.put("code",0);
        responseMap.put("msg","success");
        if(obj != null){
            responseMap.put("data", obj);
        }
        try{
            response.getWriter().write(JSON.toJSONString(responseMap));
        } catch (Exception e){
            debug(e);
        }
    }

    //设置请求头
    public HttpServletResponse setHeader(Integer seconds){
        HttpServletResponse response = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getResponse();
        response.setHeader("Content-type", "application/json;charset=UTF-8");
        response.setHeader("Access-Control-Allow-Header", "*, Content-Type, Origin, X-Mby20, X-Requested-With,ContentType");
        response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
        if(seconds != null){
            //response.setDateHeader("Expires",System.currentTimeMillis()+(seconds*1000));
        }
        String method = request.getMethod();
        if(method != null){
            if (method.equals("OPTIONS")){
                response.setStatus(204);
            }
        }
        return response;
    }

    //从cookie中获取token值
    public void getTokenFromCookie(){
        isMoblie = HttpUtil.isMoblie(request);
        if(isMoblie){
            cookie_name = "mby-live-m";
        }else{
            cookie_name = "mby-live-p";
        }

        login_as = request.getParameter("login_as");
        if(login_as != null){
            login_as = login_as.toLowerCase();
        }
        //初始化token
        token = null;
        //两种获取token的方式，看前端把token怎么处理
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                if (cookie.getName().equals(cookie_name)) {
                    token = cookie.getValue();
                    break;
                }
            }
        }
    }

    public void debug(Exception e) {
        Debug d = new Debug();
        d.setMethod(request.getMethod());
        d.setUrl(request.getRequestURI());
        if (!params.isEmpty()) {
            params.remove("content");
        }
        d.setParams(params);
        Writer w = new StringWriter();
        PrintWriter p = new PrintWriter(w);
        e.printStackTrace(p);
        String s = w.toString().replaceAll("\r|\n*", "");
        d.setError(s.replace("\tat", ""));
        d.setMessage(e.getLocalizedMessage());
        if (e instanceof MbyException) {
            MbyException ex = (MbyException) e;
            d.setData(ex.getData());
        }
        d = (Debug) mongoTool.addOne(d);
        throw new MbyException(e.toString(), d.getId(), d.getData());
    }

    public String getNow(){
        Date now = new Date();
        SimpleDateFormat format =  new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String now_str = format.format(now);
        now = null;
        format = null;
        return now_str;
    }

    /** 基于@ExceptionHandler异常处理 */
    @ExceptionHandler
    @ResponseBody
    public Map<String, Object> handleAndReturnData(HttpServletRequest request, HttpServletResponse response, Exception ex) {
        Map<String, Object> data = new HashMap<String, Object>();
        if(ex instanceof MbyException) {
            MbyException e = (MbyException)ex;
            if(e.getCode() != null){
                data.put("code", e.getCode());
            }else{
                data.put("excetion", e.getExceptionInfo());
            }
            if(e.getDebugId() != null){
                data.put("debugId", e.getDebugId());
            }
            if(e.getData() != null){
                data.put("data", e.getData());
            }
            data.put("msg",ex.getMessage());
            data.put("excetion", ex.getClass().getSimpleName());
        }else if(ex.getClass().getSimpleName().equals("UnauthorizedException")){
            Error error = initError("No Permission");
            data.put("code",error.getCode());
            data.put("msg", "No Permission");
            data.put("excetion", ex.getClass().getSimpleName());
        }else{
            data.put("msg",ex.getMessage());
            data.put("excetion", ex.getClass().getSimpleName());
        }
        return data;
    }

    public String ok = "ok";
    SimpleDateFormat ymdhms =  new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    public Error initError(String errCode){
        Error error = mongoTool.findOne("","{'id':'"+errCode+"'}",Error.class);
        if(error == null){
            error = new Error();
            error.setId(errCode);
            error.setCode(mongoTool.getAutoIncreaseID(error.getClass().getName()));;
            error.setMsg(errCode);
            mongoTool.addOne(error);
        }
        return error;
    }

    public Date getAddedDate(Date date,Integer num){
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        calendar.add(calendar.DATE,num);//把日期往后增加一天.整数往后推,负数往前移动
        date = calendar.getTime();   //这个时间就是日期往后推一天的结果
        return date;
    }

    public String loginRongCloud(String userId,String userName,String portrait) throws Exception{
        UserModel user = new UserModel()
                .setId(userId)
                .setName(userName)
                .setPortrait(portrait);
        TokenResult result = rongCloud.user.register(user);
        return result.getToken();
    }

    public Result userUpdate(String userId) throws Exception{
        User u = mongoTool.findOne("","{'id':"+userId+"}",User.class);
        String portrait;
        if(WebConstant.APP_ENV.equals("prod")){
            portrait = "http://live-asset.themobiyun.com/userIcon/"+u.getId().toString()+"?"+u.getAvatarVer();
        }else{
            portrait = "http://live-asset.themobiyun.com/userIcon/dev/"+u.getId().toString()+"?"+u.getAvatarVer();
        }
        UserModel user = new UserModel()
                .setId(userId)
                .setName(u.getUserName()+"（"+u.getRoleName().split(",")[0]+"）")
                .setPortrait(portrait);
        return rongCloud.user.update(user);
    }

    public boolean isNotNull(String str){
        if(str != null && !"".equals(str)){
            return true;
        }else{
            return false;
        }
    }

    public boolean isNotNull(Object obj){
        if(obj != null){
            return true;
        }else{
            return false;
        }
    }

    public long getSeconds(Date date1, Date date2){
        long interval = (date1.getTime() - date2.getTime())/1000;
        return interval;
    }

    public static void putRowData(WritableSheet ws, int rowNum, int columnNum, String data) throws RowsExceededException, WriteException {
        Label cell = new Label(columnNum, rowNum, "" + data);
        ws.addCell(cell);
    }

    public static void putRowTitle(WritableSheet ws, int rowNum, String[] titles) throws RowsExceededException, WriteException {
        for (int j = 0; j < titles.length; j++) {
            Label cell = new Label(j, rowNum, "" + titles[j]);
            ws.addCell(cell);
        }
    }
}
